#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 正常使用c的接口打印到屏幕，行刷新会将FILE缓冲区的内容刷新到内核缓冲区，进而输出到显示器
// 重定向到文件，行刷新变成全缓重，但在进程退出时，会将FILE缓冲区内容刷新到内核缓冲区，进而输出到显示器
// 
// 但是当在最后关闭fd时，内容还在FILE缓冲区，关闭了fd，进程结束也无法刷新到内核缓冲区，因此在文件中无法显示
// 可以fflush手动刷新缓冲区

//int main()
//{
//  close(1);
//  int fd = open("./log.txt", O_CREAT | O_WRONLY, 0644);
//
//  printf("fd = %d\n", fd);
//  fprintf(stdout, "hello\n");
//
//  //close(fd);
//  return 0;
//}


// 输出重定向无法针对标准错误 
// 打印函数是行刷新，因此就算在最后关闭close（1）也可以输出到显示器
// 但是重定向到文件无法显示，行缓存变成全缓冲
// printf/fprintf的内容存放在stdout的FILE文件缓冲区中
// 关闭close（1）,进程结束系统刷新缓冲区时，无法在刷新到内核缓冲区，也就无法显示到文件中
// fflush手动刷新即可
//int main()
//{
//  const char* msg = "stdout\n";
//  write(1, msg, strlen(msg));
//
//  const char* msg2 = "stderr\n";
//  write(2, msg2, strlen(msg2));
//  // ./myfile > log.txt
//  // ./myfile > log.txt 2>&1
//
//  printf("stdout\n");
//  fprintf(stdout, "stdout\n");
//
//  //fflush(stdout);
//  //close(1);
//  return 0;
//}



int main()
{
  const char* msg = "stdout\n";
  write(1, msg, strlen(msg));

  // stdout -> FILE* -> FILE struct ->1.fd  2.buffer-> 刷新策略-> 目标文件
  printf("sherry printf\n");
  fprintf(stdout, "sherry fprintf\n");
  fputs("sherry fputs\n", stdout);
 
  // 重定向到文件，刷新策略变为全缓冲
  // printf/fprintf/fputs 的内容到用户级缓冲区
  // “写时拷贝”，子进程拷贝父进程的缓冲区容
  // 因此重定向到文件，会发现printf/fprintf/fputs会打印两次
  // 为了消除这种情况，在创建子进程之前，刷新stdout的缓冲区
  // fork创建子进程时，子进程就没有缓冲区的数值，就不会打印两次
  
  fflush(stdout);
  fork();
  
  return 0;
}




















